// Xianjun jiao. putaoshu@msn.com; xianjun.jiao@imec.be;

#include <complex>
#include "ap_int.h"

typedef ap_int<2> int2;
typedef ap_uint<2> uint2;
typedef ap_int<4> int4;
typedef ap_int<16> int16;
typedef ap_int<32> int32;

typedef std::complex<int32> cplx32;

// also find gen_mixer_coef_padded.m
const char i_p0n5n10n15n20MHz[5][160] = {
{64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
{64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45},
{64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0},
{64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45},
{64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64, 64, -64}
};
const char q_p0n5n10n15n20MHz[5][160] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45, 0, -45, -64, -45, 0, 45, 64, 45},
{0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64, 0, -64, 0, 64},
{0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45, 0, -45, 64, -45, 0, 45, -64, 45},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};

#define INPUT_LENGTH 160

void mixer_duc(int32 d_i0[INPUT_LENGTH], int32 cfg0,
		int32 d_o[INPUT_LENGTH])
{
#pragma HLS INTERFACE ap_stable port=cfg0
#pragma HLS INTERFACE ap_ctrl_none port=return
//#pragma HLS DATAFLOW
#pragma HLS INTERFACE ap_fifo port=d_o
#pragma HLS INTERFACE axis port=d_i0

	unsigned char i;
	int32 tmp32, tmp32_o;
	cplx32 bw20_a0, c00, p00;

	int2 bw20_ant0_conj_flag;
	uint2 bw20_ant0_ch_idx;
	int4 bw20_num_shift_to_left;

	bw20_ant0_ch_idx = cfg0(1,0);
	bw20_ant0_conj_flag = (cfg0[2])?(-1):1;
	bw20_num_shift_to_left = cfg0(31,28);

	for (i=0; i<INPUT_LENGTH; i++)
	{
#pragma HLS PIPELINE
		tmp32 = d_i0[i];

		bw20_a0  = cplx32((int16)tmp32(15,0),(int16)tmp32(31,16));

		// bw20 mixer
		c00 = cplx32(i_p0n5n10n15n20MHz[bw20_ant0_ch_idx][i], bw20_ant0_conj_flag*q_p0n5n10n15n20MHz[bw20_ant0_ch_idx][i]);

		p00 = bw20_a0*c00;

		// gain module for bw20
		p00  = cplx32((((int32)real(p00))<<bw20_num_shift_to_left)/64,(((int32)imag(p00))<<bw20_num_shift_to_left)/64);

		tmp32_o(15,0)  = real(p00);
		tmp32_o(31,16) = imag(p00);

		d_o[i] = tmp32_o;
	}
}
